using System;
using System.Text;
using Bittorrent.Bencode.Collections;
using Bittorrent.Bencode;
using Bittorrent.File.Exceptions;

namespace Bittorrent.File
{
    public class MetaFile
    {
        private readonly Dictionary _dictionary;

        /// <summary>
        /// Initializes a new instance of the MetaFile class.
        /// </summary>
        public MetaFile() {
        }

        internal MetaFile(Dictionary dictonary) {
            _dictionary = dictonary;
            Length = GetLength(_dictionary);
            Path = GetPath(_dictionary);
        }

        /// <summary>
        /// Gets length of the file in bytes.
        /// </summary>
        public long Length { get; private set; }

        /// <summary>
        /// Gets file path.
        /// </summary>
        public string Path { get; private set; }

        private static long GetLength(Dictionary dictonary) {
            if (!dictonary.ContainsKey("length")) {
                throw new TorrentFileException("Mallformed torrent file: no torrent file length was found.");
            }

            var length = dictonary["length"] as Integer;
            if (length == null) {
                throw new TorrentFileException("Mallformed torrent file: torrent file length was not represented by a Bencode.Integer");
            }

            return length.Value;
        }

        private static string GetPath(Dictionary dictonary) {
            if (!dictonary.ContainsKey("path")) {
                throw new TorrentFileException("Mallformed torrent file: no torrent file path was found.");
            }

            var paths = dictonary["path"] as List;
            if (paths == null) {
                throw new TorrentFileException("Mallformed torrent file: torrent file path was not represented by a Bencode.List");
            }

            var strBuilder = new StringBuilder();

            int i = 0;
            foreach (var item in paths) {
                var str = item as ByteString;
                if (str == null) {
                    throw new TorrentFileException("Mallformed torrent file: torrent file path list have to be a Bencode.ByteString");
                }

                strBuilder.Append(str.String);

                // Append a path separator except for the last entry that should be a file
                ++i;
                if (i != paths.Count) {
                    strBuilder.Append(System.IO.Path.DirectorySeparatorChar);
                }
            }

            return strBuilder.ToString();
        }

        internal Dictionary GetDictionary() {
            var dictionary = new Dictionary();

            dictionary.Add((ByteString)"length", new Integer { Value = Length });
            if (string.IsNullOrEmpty(Path)) {
                throw new TorrentFileException("Path is not a optional property for MetaFile");
            }
            else {
                dictionary.Add((ByteString)"path", new ByteString { String = Path });
            }

            return dictionary;
        }
    }
}
